package com.xindacloud.sms.adapter.service.notify.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.google.gson.Gson;
import com.xindacloud.sms.adapter.bo.CheckPhoneNumberBO;
import com.xindacloud.sms.adapter.bo.SubmitMessageBO;
import com.xindacloud.sms.adapter.dto.SqsSubmitMessageParamDTO;
import com.xindacloud.sms.adapter.entity.*;
import com.xindacloud.sms.adapter.exception.ServiceException;
import com.xindacloud.sms.adapter.service.business.*;
import com.xindacloud.sms.adapter.service.notify.INotifyService;
import com.xindacloud.sms.adapter.service.sms.ISubmitMessageService;
import com.xindacloud.sms.adapter.utils.Base64DecodeHelp;
import com.xindacloud.sms.adapter.utils.PhoneUtil;
import com.xindacloud.sms.adapter.utils.StatusEum;
import com.xindacloud.sms.adapter.utils.UnionResultHelp;
import com.xindacloud.sms.adapter.vo.SubmitMessageResultVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@Service("submitSmsNotifyService")
@Slf4j
public class SubmitSmsNotifyServiceImpl implements INotifyService {

    private final ISmsAgentService smsAgentService;

    private final ISmsAgentGroupService smsAgentGroupService;

    private final ISmsUserAllowOperatorService smsUserAllowOperatorService;

    private final ISmsAgentRouteService smsRouteService;

    private final ISmsSubmissionRecordService smsSubmissionRecordService;

    private final ISmsUserService smsUserService;

    private final Map<String, ISubmitMessageService> submitMessageServiceStrategyMap = new ConcurrentHashMap<>();

    @Autowired
    public SubmitSmsNotifyServiceImpl(Map<String, ISubmitMessageService> submitMessageServiceStrategyMap,
                                      ISmsAgentService smsAgentService,
                                      ISmsAgentGroupService smsAgentGroupService,
                                      ISmsUserAllowOperatorService smsUserAllowOperatorService,
                                      ISmsAgentRouteService smsRouteService,
                                      ISmsSubmissionRecordService smsSubmissionRecordService,
                                      ISmsUserService userService) {
        this.submitMessageServiceStrategyMap.clear();
        submitMessageServiceStrategyMap.forEach(this.submitMessageServiceStrategyMap::put);
        this.smsAgentService = smsAgentService;
        this.smsAgentGroupService = smsAgentGroupService;
        this.smsUserAllowOperatorService = smsUserAllowOperatorService;
        this.smsRouteService = smsRouteService;
        this.smsSubmissionRecordService = smsSubmissionRecordService;
        this.smsUserService = userService;
    }

    @SuppressWarnings("unchecked")
    private SubmitMessageResultVO submitMessage(SubmitMessageBO submitMessageBO) {

        final String recipient = submitMessageBO.getRecipient();
        final Integer userId = submitMessageBO.getUserId();
        final String messageBody = submitMessageBO.getMessageBody();
        final String taskId = submitMessageBO.getTaskId();
        final String senderId = submitMessageBO.getSenderId();
        final Integer messageCount = submitMessageBO.getMessageCount() == 0 ? 1 : submitMessageBO.getMessageCount();
        String countryCode = "";
        String countryPrefix = "";
        String agentId = "";
        Optional.ofNullable(recipient)
                .filter(StringUtils::isNotEmpty)
                .orElseThrow(() -> new ServiceException("目标号码不能为空", UnionResultHelp.StatusEnum.ParamsFail.code()));

        final SmsUser smsUser = smsUserService.queryUserInfoById(userId);
        try {
            if (Objects.isNull(smsUser) || smsUser.getBalance().doubleValue() <= 0) {
                throw new ServiceException("账户余额不足", UnionResultHelp.StatusEnum.Fail.code());
            }
            //检查号码所属国家
            final CheckPhoneNumberBO phoneNumberBO = PhoneUtil.getPoneNumber(recipient);
            if (Objects.isNull(phoneNumberBO)) {
                throw new ServiceException("号码不合法", UnionResultHelp.StatusEnum.ParamsFail.code());
            }
            countryCode = phoneNumberBO.getRegion();
            countryPrefix = String.valueOf(phoneNumberBO.getCountryPrefix());
            //获取手机所属运营商名称
            final String networkName = PhoneUtil.getCarrier(String.valueOf(phoneNumberBO.getNationalNumber()), Integer.parseInt(countryPrefix));
            log.info("国家简码:{},国家号码前缀:{},网络名称:{}", countryCode, countryPrefix, networkName);

            //获取最优惠或者指定的运营商对应的平台发送
            final SmsUserAllowOperator allowOperator = this.chooseAssignationOperators(userId, countryCode, countryPrefix, networkName);
            //获取通道代理商的api_key,apiSecret
            final SmsAgent agent = smsAgentService.queryAgentById(allowOperator.getAgentId());
            //获取通道代理商组名
            final SmsAgentGroup smsAgentGroup = smsAgentGroupService.queryOneAgentInfoById(agent.getGroupId());
            log.info("###使用:{},{}平台发送短信", smsAgentGroup.getGroupName(), agent.getAgentName());
            final SmsAgentRoute smsAgentRoute = smsRouteService.querySmsRouteById(smsAgentGroup.getRouteId());
            log.info("###获取到的路由ID:{},路由服务：{}", smsAgentRoute.getRouteId(), smsAgentRoute.getRouteServiceBeanId());
            //根据通道代理商组名路由到不同的服务发送短信
            agentId = agent.getAgentId();
            SubmitMessageBO messageBO = SubmitMessageBO.builder()
                    .apiKey(Base64DecodeHelp.decode(agent.getApiKey()))
                    .apiSecret(Base64DecodeHelp.decode(agent.getApiSecret()))
                    .apiUrl(agent.getApiUrl())
                    .senderId(senderId)
                    .callBackUrl(agent.getCallBackUrl())
                    .messageBody(messageBody)
                    .messageCount(messageCount)
                    .userId(userId)
                    .taskId(taskId)
                    .recipient(recipient)
                    .countryCode(countryCode)
                    .countryPrefix(countryPrefix)
                    .agentId(agentId)
                    .costPrice(allowOperator.getCostPrice())
                    .build();

            return (SubmitMessageResultVO) submitMessageServiceStrategyMap
                    .get(smsAgentRoute.getRouteServiceBeanId())
                    .submitMessage(messageBO);

        } catch (Exception e) {
            log.error("### SubmitSmsNotifyServiceImpl 提交短信异常:{}", e.getMessage());
            int errorCode = 400;
            String errorMessage = "Service Error";
            if (e instanceof ServiceException) {
                final ServiceException serviceException = (ServiceException) e;
                errorCode = serviceException.getErrorCode();
                errorMessage = serviceException.getMessage();
            }
            smsSubmissionRecordService.updateSmsSubmissionRecordFor(SmsSubmissionRecord.builder()
                    .submitStatusCode(errorCode)
                    .errorText(errorMessage)
                    .agentId(agentId)
                    .costPrice(BigDecimal.ZERO)
                    .free(BigDecimal.ZERO)
                    .countryCode(countryCode)
                    .prefix(countryPrefix)
                    .finalStatus(StatusEum.FAILED.desc)
                    .sendTo(recipient)
                    .taskId(taskId)
                    .userId(userId)
                    .build());
        }
        return null;
    }

    @NotNull
    private SmsUserAllowOperator chooseAssignationOperators(Integer userId, String countryCode, String prefix, String networkName) {

        //查询所有运营商价格最高列表按价格降序
        final List<SmsUserAllowOperator> minCostPricingList = smsUserAllowOperatorService
                .queryMinCostPriceOrderByAsc(userId, countryCode, prefix);

       /* final List<SmsUserAllowOperator> smsUserAllowOperators = smsUserAllowOperatorService
                .queryUserAllowOperatorByNetworkName(userId, countryCode, prefix, networkName);

        if (CollectionUtils.isNotEmpty(smsUserAllowOperators)) {
            minCostPricingList.addAll(smsUserAllowOperators);

        } else {
            minCostPricingList.addAll(smsUserAllowOperatorService
                    .queryUserAllowOperatorByNetworkName(userId, countryCode, prefix, ""));
        }*/

        if (CollectionUtils.isEmpty(minCostPricingList)) {
            throw new ServiceException("没有可用的服务通道或服务已被禁用.", UnionResultHelp.StatusEnum.InnerError.code());
        }

        final List<SmsUserAllowOperator> filterPriceList = new ArrayList<>();
        //把禁用的代理账户过滤掉
        final List<SmsAgent> smsAgents = smsAgentService.queryAvailableAgentList(minCostPricingList.stream()
                .map(SmsUserAllowOperator::getAgentId)
                .collect(Collectors.toList()));
        for (SmsUserAllowOperator allowOperator : minCostPricingList) {
            for (SmsAgent agent : smsAgents) {
                if (Objects.equals(allowOperator.getAgentId(), agent.getAgentId())) {
                    filterPriceList.add(allowOperator);
                }
            }
        }
        if (CollectionUtils.isEmpty(filterPriceList)) {
            throw new ServiceException("没有可用的服务通道或服务已被禁用.", UnionResultHelp.StatusEnum.InnerError.code());
        }
        final SmsUserAllowOperator userAllowOperator = filterPriceList.get(0);
        log.info("###当前用户获取最优惠通道agentId:{},成本价:{}", userAllowOperator.getAgentId(), userAllowOperator.getCostPrice());
        return userAllowOperator;
    }

    @Override
    public void perform(String data) {
        SqsSubmitMessageParamDTO sqsSubmitMessageDTO = new Gson().fromJson(data, SqsSubmitMessageParamDTO.class);
        try {
            sqsSubmitMessageDTO.getRecipientList()
                    .forEach(recipient -> this.submitMessage(SubmitMessageBO
                            .builder()
                            .messageBody(sqsSubmitMessageDTO.getMessageBody())
                            .messageCount(sqsSubmitMessageDTO.getMessageCount())
                            .userId(sqsSubmitMessageDTO.getUserId())
                            .taskId(sqsSubmitMessageDTO.getTaskId())
                            .senderId(sqsSubmitMessageDTO.getSender())
                            .recipient(recipient)
                            .build()));
        } catch (Exception e) {
            log.error("处理发送短信异常:{}", e.getMessage(), e);
        }

    }
}
